package fr.sportcom.sportcom.controller;

import java.lang.ref.WeakReference;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import fr.sportcom.sportcom.R;
import fr.sportcom.sportcom.SportComApplication;
import fr.sportcom.sportcom.adapter.SportsListAdapter;
import fr.sportcom.sportcom.model.AdsManager;
import fr.sportcom.sportcom.model.CEvent;
import fr.sportcom.sportcom.model.CSport;
import fr.sportcom.sportcom.model.CustomHttpClient;

import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.ToggleButton;

public class CreateEventActivity extends FragmentActivity
implements DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener, DialogInterface.OnClickListener, TextWatcher {

	//// EXTRA
	// En entr�e :
	public final static String EXTRA_ACTION = "fr.sportcom.sportcom.extra.cea.ACTION";
	public final static String EXTRA_EVENT = "fr.sportcom.sportcom.extra.cea.EVENT";

	// Valeur d'ACCTION:
	public final static int CREAT = 1, EDIT = 2;

	private static final int THRESHOLD = 4;

	private int pAction;
	private CEvent pEvent;

	// Variable de valeur.
	private int mSportId;
	private int mDateDay = 0;
	private int mDateMonth = 0;
	private int mDateYear = 0;
	private int mBeginH = 0;
	private int mBeginM = 0;
	private int mEndH = -1;
	private int mEndM = 0;
	private int mNbPart = 0;
	private String mAddr = "";
	private Double longitude = null;
	private Double latitude = null;
	private String mDesc = "";
	private boolean mIsPrivate = false;

	// UI references.
	private AutoCompleteTextView mAddressView;
	private Button  mSportView;
	private Button  mDateView;
	private Button  mBeginView;
	private Button  mEndView;
	private Button  mApplyView;
	private NumberPicker mNumPickerView;
	private ToggleButton mTypeView;
	private EditText mDescriptionView;

	private DialogFragment mDatePicker = new DatePickerFragment();
	private DialogFragment mTimePicker = new TimePickerFragment();
	private boolean isBeginEnd = true; // true: Begin / false: End
	private SportDialogFragment mSportPicker = new SportDialogFragment();
	private ArrayList<CSport> lSport = new ArrayList<CSport>();
	private RefreshSportListTask mListTask;
	private RefreshAddrAutocompTask mListAddrAutocompTask = null;
	private ArrayAdapter<String> autoCompleteAdapter;

	private int userId;
	private EventCreatTask mRegTask;

	public static Intent prepareIntent(Context context, int action, CEvent event) {
		return new Intent(context, CreateEventActivity.class)
		.putExtra(EXTRA_ACTION, action)
		.putExtra(EXTRA_EVENT, event);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//setContentView(R.layout.activity_create_event);
		setContentView(R.layout.sponso_layout);
		View appContent = LayoutInflater.from(this).inflate(
				R.layout.activity_create_event, 
				(ViewGroup) this.findViewById(R.id.app_content), 
				false);
		((LinearLayout)this.findViewById(R.id.app_content)).addView(appContent);
		AdsManager.displayAds(this);
		
		mAddressView = (AutoCompleteTextView) findViewById(R.id.auto_comp_addr);
		mSportView = (Button) findViewById(R.id.btn_pick_sport);
		mDateView = (Button) findViewById(R.id.btn_pick_date);
		mBeginView = (Button) findViewById(R.id.btn_pick_begin);
		mEndView = (Button) findViewById(R.id.btn_pick_end);
		mApplyView = (Button) findViewById(R.id.create_event_button);
		mNumPickerView = (NumberPicker) findViewById(R.id.np_nb_part);
		mTypeView = (ToggleButton) findViewById(R.id.sw_type);
		mDescriptionView = (EditText) findViewById(R.id.txt_description);
		
		// Init autoComplete
		mAddressView.addTextChangedListener(this);
		//mAddressView.setOnItemSelectedListener(this);
		mAddressView.setThreshold(THRESHOLD);
		// L'adapter
		autoCompleteAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, new ArrayList<String>());
		autoCompleteAdapter.setNotifyOnChange(false);
		mAddressView.setAdapter(autoCompleteAdapter);

		userId = ((SportComApplication) (this.getApplication())).getLoggedUser().getId();

		mListTask = new RefreshSportListTask();
		mListTask.execute();

		// On recupere les parametre
		Intent i = getIntent();
		pAction = i.getIntExtra(EXTRA_ACTION, 1);
		pEvent = i.getParcelableExtra(EXTRA_EVENT);
		DateFormat FormatDate = new SimpleDateFormat("dd/MM/yyyy", Locale.FRANCE);
		DateFormat FormatHour = new SimpleDateFormat("HH:mm", Locale.FRANCE);
		switch(pAction){
		case EDIT :
			mSportView.setText(pEvent.getSport().getName());
			mSportId = pEvent.getSport().getId();
			mDateView.setText(FormatDate.format(pEvent.getBegin()));
			//pEvent.getDate(mDateYear, mDateMonth, mDateDay);
			mDateYear = pEvent.getDate("yyyy");
			mDateMonth = pEvent.getDate("MM");
			mDateDay = pEvent.getDate("dd");
			mBeginView.setText(FormatHour.format(pEvent.getBegin()));
			//pEvent.getBHour(mBeginH, mBeginM);
			mBeginH = pEvent.getBHour("HH");
			mBeginM = pEvent.getBHour("mm");
			if(pEvent.getDuration() != 0) {
				mEndView.setText(FormatHour.format(pEvent.getEnd()));
			}
			//pEvent.getEHour(mEndH, mEndM);
			mEndH = pEvent.getEHour("HH");
			mEndM = pEvent.getEHour("mm");
			mNbPart = pEvent.getNbparticipants();
			mDesc = pEvent.getDescription();
			mIsPrivate = pEvent.isPrivate();
			mTypeView.setChecked(mIsPrivate);
			mDescriptionView.setText(mDesc);
			break;
		case CREAT :
			break;
		}

		((DatePickerFragment) mDatePicker).linkListener(this);
		((TimePickerFragment) mTimePicker).linkListener(this);
		
		mNumPickerView.setMinValue(0);
		mNumPickerView.setMaxValue(100);
		mNumPickerView.setValue(mNbPart);

		mSportView.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				mSportPicker.show(getSupportFragmentManager(), "sportPicker");
			}
		});

		mDateView.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				mDatePicker.show(getSupportFragmentManager(), "datePicker");
			}
		});

		mBeginView.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				isBeginEnd = true;
				mTimePicker.show(getSupportFragmentManager(), "timePicker");
			}
		});

		mEndView.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				isBeginEnd = false;
				mTimePicker.show(getSupportFragmentManager(), "timePicker");
			}
		});

		mApplyView.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				attemptCreate();
			}
		});
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		AdsManager.displayAds(this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_create_event, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			// This ID represents the Home or Up button. In the case of this
			// activity, the Up button is shown. Use NavUtils to allow users
			// to navigate up one level in the application structure. For
			// more details, see the Navigation pattern on Android Design:
			//
			// http://developer.android.com/design/patterns/navigation.html#up-vs-back
			//
			//NavUtils.navigateUpFromSameTask(this);
			this.finish();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	public void attemptCreate() {
		if (mRegTask != null) {
			return;
		}

		// Reset errors.
		mAddressView.setError(null);
		mSportView.setError(null);
		mDateView.setError(null);
		mBeginView.setError(null);
		mEndView.setError(null);
		mDescriptionView.setError(null);
		
		mAddr = mAddressView.getText().toString();
		mDesc = mDescriptionView.getText().toString();
		mNbPart = mNumPickerView.getValue();
		mIsPrivate = mTypeView.isChecked();
		
		// Store values at the time of the login attempt.
		//longitude = Double.parseDouble((String) ((TextView) findViewById(R.id.longitude)).getText());
		//latitude = Double.parseDouble((String) ((TextView) findViewById(R.id.latitude)).getText());

		boolean cancel = false;
		View focusView = null;

		// Check for a valid confirmation password.
		if (mBeginH == -1) {
			mBeginView.setError(getString(R.string.error_field_required));
			focusView = mBeginView;
			cancel = true;
		}
		if (mDateYear == 0) {
			mDateView.setError(getString(R.string.error_field_required));
			focusView = mDateView;
			cancel = true;
		}
		if (mSportId == 0) {
			mSportView.setError(getString(R.string.error_field_required));
			focusView = mSportView;
			cancel = true;
		}
		if(mAddr.isEmpty()) {
			mAddressView.setError(getString(R.string.error_field_required));
			focusView = mAddressView;
			cancel = true;
		}
		if(mDesc.isEmpty()) {
			mDescriptionView.setError(getString(R.string.error_field_required));
			focusView = mDescriptionView;
			cancel = true;
		}

		if (cancel) {
			// There was an error; don't attempt login and focus the first
			// form field with an error.
			focusView.requestFocus();
		} else {
			// Show a progress spinner, and kick off a background task to
			// perform the user login attempt.
			//mLoginStatusMessageView.setText(R.string.login_progress_signing_in);
			//showProgress(true);
			mRegTask = new EventCreatTask();
			mRegTask.link(this);
			mRegTask.execute();
		}
	}


	private class EventCreatTask extends AsyncTask<Void, Void, Boolean> {

		private WeakReference<CreateEventActivity> mActivity = null;

		@Override
		protected Boolean doInBackground(Void... params) {

			if(longitude == null || latitude == null) {
				Geocoder geo = new Geocoder(CreateEventActivity.this);
				try {
					List<Address> lAdd;
					lAdd = geo.getFromLocationName(mAddr, 1);
					if(lAdd.size() != 0) {
						latitude = lAdd.get(0).getLatitude();
						longitude = lAdd.get(0).getLongitude();
					}
				}
				catch (Exception e) {
					return false;
				}
			}
			
			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
			String temp = String.format("%04d", mDateYear)
					+ "-" + String.format("%02d", mDateMonth)
					+ "-" + String.format("%02d", mDateDay)
					+ " " + String.format("%02d", mBeginH)
					+ ":" + String.format("%02d", mBeginM) + ":00";
			param.add(new BasicNameValuePair("evt_debut", temp));
			if(mEndH == -1) {
				temp = "0000-00-00 00:00:00";
			}
			else {
				temp = String.format("%04d", mDateYear)
						+ "-" + String.format("%02d", mDateMonth)
						+ "-" + String.format("%02d", mDateDay)
						+ " " + String.format("%02d", mEndH)
						+ ":" + String.format("%02d", mEndM) + ":00";
			}
			param.add(new BasicNameValuePair("evt_fin", temp));

			param.add(new BasicNameValuePair("evt_latitude", ""+latitude));
			param.add(new BasicNameValuePair("evt_longitude", ""+longitude));
			param.add(new BasicNameValuePair("spr_id", ""+mSportId));
			String bPrivate = mIsPrivate ? "1" : "0";
			param.add(new BasicNameValuePair("evt_prive", bPrivate));
			param.add(new BasicNameValuePair("evt_nombreParticipant", ""+mNbPart));
			param.add(new BasicNameValuePair("uti_id", ""+userId));
			param.add(new BasicNameValuePair("com_contenu", mDesc));

			try {
				//Thread.sleep(5000);
				jObj = request.postData("createEvent", param);

				if(jObj.getInt("back") != 0) {
					return false;
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			mRegTask = null;

			if (!success) {
				Toast.makeText(mActivity.get(), "Une erreur est survenue.", Toast.LENGTH_LONG).show();
				return;
			}

			finish();
		}

		public void link (CreateEventActivity pActivity) {
			mActivity = new WeakReference<CreateEventActivity>(pActivity);
		}
	}



	public static class DatePickerFragment extends DialogFragment {
		private WeakReference<DatePickerDialog.OnDateSetListener> mActivity;
		private Integer mYear = null;
		private Integer mMonth = null;
		private Integer mDay = null;

		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			// Use the current date as the default date in the picker
			final Calendar c = Calendar.getInstance();
			int year = c.get(Calendar.YEAR);
			int month = c.get(Calendar.MONTH);
			int day = c.get(Calendar.DAY_OF_MONTH);
			if(mYear != null && mMonth != null && mDay != null) {
				year = mYear;
				month = mMonth;
				day = mDay;
			}

			// Create a new instance of DatePickerDialog and return it
			Dialog picker = new DatePickerDialog(getActivity(), mActivity.get(), year, month, day);
		    picker.setCanceledOnTouchOutside(true);
		    picker.setCancelable(true);
			((AlertDialog) picker).setButton(DialogInterface.BUTTON_NEGATIVE, 
					getString(R.string.cancel), 
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							if (which == DialogInterface.BUTTON_NEGATIVE) {
								dialog.dismiss();
							}
						}
					});
			((AlertDialog) picker).setButton(DialogInterface.BUTTON_POSITIVE, 
					"OK", 
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							if (which == DialogInterface.BUTTON_POSITIVE) {
							}
						}
					});
			return picker;
		}

		public void linkListener(DatePickerDialog.OnDateSetListener c) {
			mActivity = new WeakReference<DatePickerDialog.OnDateSetListener>(c);
		}
		
		public void setDate(Integer year, Integer month, Integer day) {
			mYear = year;
			mMonth = month;
			mDay = day;
		}
	}
	public static class TimePickerFragment extends DialogFragment {
		private WeakReference<TimePickerDialog.OnTimeSetListener> mActivity;
		private Integer mHour = null;
		private Integer mMinute = null;

		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			// Use the current time as the default values for the picker
			final Calendar c = Calendar.getInstance();
			int hour = c.get(Calendar.HOUR_OF_DAY);
			int minute = c.get(Calendar.MINUTE);
			if(mHour != null && mMinute != null) {
				hour = mHour;
				minute = mMinute;
			}

			// Create a new instance of TimePickerDialog and return it
			Dialog picker = new TimePickerDialog(getActivity(), mActivity.get(), hour, minute,
					true);
		    picker.setCanceledOnTouchOutside(true);
		    picker.setCancelable(true);
			((AlertDialog) picker).setButton(DialogInterface.BUTTON_NEGATIVE, 
					getString(R.string.cancel), 
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							if (which == DialogInterface.BUTTON_NEGATIVE) {
								dialog.dismiss();
							}
						}
					});
			((AlertDialog) picker).setButton(DialogInterface.BUTTON_POSITIVE, 
					"OK", 
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							if (which == DialogInterface.BUTTON_POSITIVE) {
							}
						}
					});
			return picker;
		}

		public void linkListener(TimePickerDialog.OnTimeSetListener c) {
			mActivity = new WeakReference<TimePickerDialog.OnTimeSetListener>(c);
		}
		
		public void setTime(Integer hour, Integer minute) {
			mHour = hour;
			mMinute = minute;
		}
	}

	@Override
	public void onDateSet(DatePicker view, int year, int month, int day) {
		mDateDay = day;
		mDateMonth = month +1;
		mDateYear = year;

		mDateView.setText(String.format("%02d/%02d/%04d", mDateDay, mDateMonth, mDateYear));
	}

	@Override
	public void onTimeSet(TimePicker view, int hour, int min) {
		if(isBeginEnd) {
			mBeginH = hour;
			mBeginM = min;
			
			mBeginView.setText(String.format("%02d:%02d", mBeginH, mBeginM));
		}
		else {
			mEndH = hour;
			mEndM = min;
			
			mEndView.setText(String.format("%02d:%02d", mEndH, mEndM));
		}
	}

	private class RefreshSportListTask extends AsyncTask<Void, Void, Boolean> {

		@Override
		protected Boolean doInBackground(Void... params) {

			CustomHttpClient request = new CustomHttpClient();
			JSONObject jObj = null;
			try {
				//Thread.sleep(5000);
				jObj = request.postData("loadSportList");

				if(jObj.getInt("back") != 0) {
					return false;
				}

				lSport.clear();
				JSONArray list = jObj.getJSONArray("list");
				for(int i=0; i<list.length(); i++) {
					CSport spr = new CSport(
							list.getJSONObject(i).getInt("spr_id"), 
							list.getJSONObject(i).getString("spr_libelle")
							);
					lSport.add(spr);
				}

			} catch (Exception e) {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {

			if (!success) {
				Toast.makeText(CreateEventActivity.this, "Une erreur est survenue.", Toast.LENGTH_LONG).show();
				return;
			}

			mSportPicker.initList(CreateEventActivity.this, lSport);
		}
	}
	public static class SportDialogFragment extends DialogFragment {
		private AlertDialog.Builder builder;

		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			return builder.create();
		}

		public void initList(CreateEventActivity pActivity, ArrayList<CSport> list) {
			//builder = new AlertDialog.Builder(getActivity());
			builder = new AlertDialog.Builder(pActivity);
			builder.setTitle(R.string.set_sport);
			SportsListAdapter adapt = new SportsListAdapter(pActivity, list);
			builder.setAdapter(adapt, pActivity);
		}
	}

	@Override
	public void onClick(DialogInterface dialog, int pos) {
		mSportId = lSport.get(pos).getId();
		mSportView.setText(lSport.get(pos).getName());
	}



	@Override
	public void afterTextChanged(Editable arg0) {
		setAutocomplete(mAddressView.getText().toString());
	}

	@Override
	public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}

	@Override
	public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {		
		setAutocomplete(mAddressView.getText().toString());
	}
	
	private void setAutocomplete(String input) {
		if(mListAddrAutocompTask != null) {
			return;
		}

		mListAddrAutocompTask = new RefreshAddrAutocompTask();
		mListAddrAutocompTask.execute(input);
	}

	private class RefreshAddrAutocompTask extends AsyncTask<String, Void, Boolean> {
		private List<Address> lAdd;

		@Override
		protected Boolean doInBackground(String... params) {
			Geocoder geo = new Geocoder(CreateEventActivity.this);
			String value = params[0];
			if(value.length() >= THRESHOLD && !value.isEmpty()) {
				try {
					lAdd = geo.getFromLocationName(value, 5);
				}
				catch (Exception e) {
					return false;
				}
			}
			else {
				return false;
			}

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			if (success && lAdd.size() != 0) {

				autoCompleteAdapter.clear();
				String temp;
				for (Address a : lAdd) {
					temp = ""+ a.getAddressLine(0)+" "+a.getPostalCode()+" "+a.getLocality();
					autoCompleteAdapter.add(temp);
				}
				autoCompleteAdapter.notifyDataSetChanged();
				
			}
			mListAddrAutocompTask = null;
		}
	}
}
